package com.hsqyz.esp32_led.common.utils;

import cn.hutool.extra.spring.SpringUtil;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

/**
 * spring工具类
 *
 * @author lcz
 */
@Component
public final class SpringUtils extends SpringUtil {

    /**
     * 检查BeanFactory中是否包含指定名称的bean。
     *
     * @param name 要检查的bean的名称。
     * @return 如果BeanFactory包含一个与所给名称匹配的bean定义，则返回true；否则返回false。
     */
    public static boolean containsBean(String name) {
        // 直接调用getBeanFactory()方法获取当前的BeanFactory实例，并检查指定名称的bean是否存在。
        return getBeanFactory().containsBean(name);
    }


    /**
     * 判断给定名称的bean是否为单例类型。
     *
     * @param name 要查询的bean的名称。
     * @return 如果bean是单例类型，则返回true；否则返回false。
     * @throws NoSuchBeanDefinitionException 如果指定名称的bean不存在。
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        // 通过调用getBeanFactory()方法获取当前应用上下文中的bean工厂，
        // 然后通过bean工厂来判断指定名称的bean是否为单例类型。
        return getBeanFactory().isSingleton(name);
    }


    /**
     * 根据给定的名称获取注册对象的类型。
     *
     * @param name 要查询的bean的名称。这是在注册bean时使用的唯一标识符。
     * @return 类型为Class<?>的bean类型。这可以是任何类型的Class对象，表示
     *         给定bean实例化的类或接口。
     * @throws NoSuchBeanDefinitionException 如果请求的bean不存在或bean工厂不包含该bean的定义，
     *         则抛出此异常。这有助于早期识别配置错误。
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return getBeanFactory().getType(name);
    }


    /**
     * 获取给定Bean名称的别名数组。
     *
     * @param name 要查询别名的Bean的名称。
     * @return 返回该Bean定义的别名数组。如果没有别名，返回空数组。
     * @throws NoSuchBeanDefinitionException 如果指定的Bean不存在，则抛出此异常。
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        // 通过调用getBeanFactory方法获取BeanFactory实例，并进一步调用其getAliases方法来获取别名数组。
        return getBeanFactory().getAliases(name);
    }


    /**
     * 获取AOP代理对象。
     *
     * @param invoker 目标对象，即需要被AOP代理的对象。这个参数被直接传递给方法，并没有实际使用，
     *                主要是为了符合某些框架或调用约定的需要。
     * @return 返回当前AOP上下文中的代理对象。该代理对象与原始对象具有相同的接口，
     *         调用代理对象的方法会触发AOP框架执行相应的切面逻辑。
     * @param <T> 通配符类型参数，用于泛型类型安全检查，确保返回的对象类型与传入的参数类型一致。
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker) {
        // 通过AopContext的currentProxy方法获取当前的AOP代理对象。
        // 该方法是Spring AOP框架的一部分，用于在AOP上下文中获取当前的代理对象。
        return (T) AopContext.currentProxy();
    }



    /**
     * 获取spring上下文
     */
    public static ApplicationContext context() {
        return getApplicationContext();
    }

}
